/* 
Pimpas Release Date => 13/08/07 14:11:14
 */
if(!window.pimpas)
	pimpas = window.pimpas = [];

var Class = {
  create: function() {
    return function() {
      this.initialize.apply(this, arguments);
    }
  }
}
	
pimpas.Extends = function(Object1, Object2) {
	for(var property in Object2)
		Object1[property] = Object2[property];
}
pimpas.Object = Class.create( );

pimpas.Extends(pimpas, 
	   {
		   IncludeJS: function(src, pimpasSource) {
				var headers = document.getElementsByTagName("head");
				if(headers.length == 0)
					throw "No headers Found";
				
				var header = headers[0];
				if(pimpasSource == null || pimpasSource == undefined) pimpasSource = true;
				
				var script = document.createElement("SCRIPT");
				script.setAttribute("type", "text/javascript");
				
				if(pimpasSource) {
					var pimpasScript = pimpas.FindJS( 'pimpas.js' );
					script.setAttribute("src", pimpasScript.src.replace("pimpas.js", src));
					pimpas.insertAfter(pimpasScript.parentNode, script, pimpasScript);
				} else
					pimpas.insertAfter(header, script, null);
		   },
		   FindJS: function(src) {
				var headers = document.getElementsByTagName("head");
				if(headers.length == 0)
					throw "No headers Found";
				
				var header = headers[0];
				for(var i=0;i<header.childNodes.length;i++)
					if(header.childNodes[i].tagName == 'SCRIPT')
						if(header.childNodes[i].src.endsWith(src)) return header.childNodes[i];
				return null;
		   },
		   RequireJS: function(src) {
			   var script = pimpas.FindJS(src);
			   if(script == null)
					pimpas.IncludeJS( src );
		   },
		   insertAfter: function(parent, newNode, refNode) {
			   var newRefNode = null;
			   if(refNode != null)
					for(var i=0;i<parent.childNodes.length;i++) {
						if(parent.childNodes[i] == refNode) {
							if(parent.childNodes[i+1] != null) {
								newRefNode = parent.childNodes[i+1];
								break;
							}
						}
					}
				if(newRefNode != null)
					parent.insertBefore(newNode, newRefNode);
				else
					parent.appendChild(newNode);
		   }
	   }
);

pimpas.Extends(pimpas.Object,
   {
	   id: null,
	   log: null,
	   initialize: function() {
	    	this.id = pimpas.globalID++;
			this.log = new pimpas.Log();
	   }
   }
);

pimpas.Extends(Function.prototype,	 {
			   bind: function() {
    				var method = this;
					var args = new Array();
					for(var i=0;i<arguments.length;i++)
						args.push(arguments[i]);
					var object = args.shift();
					return function() {
						return method.apply(object, args);
					};
			   }
		}
);
pimpas.Extends(pimpas, {
			   		emptyFunction: function(){},
					globalID: 0,
					scriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
					version: 1.0
			   }
);
pimpas.Extends(Array.prototype,
	{
		have: function(value) {
			for(var i=0;i<this.length;i++)
				if(this[i] == value) return true;	
			return false;
		},
		clear: function() {
			while(this.length>0) this.pop( );
		},
		remove: function(value) {
			if(!this.have(value)) return;
			var a = new Array();
			for(var i=0;i<this.length;i++)
				if(this[i] != value) a.push(this[i]);
			this.clear( );
			while(a.length>0) this.push(a.pop());
			return value;
		}
	}
);

pimpas.Extends(String.prototype,
	{
	  stripTags: function() {
		return this.replace(/<\/?[^>]+>/gi, '');
	  },
	  stripScripts: function() {
		return this.replace(new RegExp(pimpas.scriptFragment, 'img'), '');
	  },
	  extractScripts: function() {
		var matchAll = new RegExp(pimpas.scriptFragment, 'img');
		var matchOne = new RegExp(pimpas.scriptFragment, 'im');
		
		var result = (this.match(matchAll) || []);
		for(var i=0;i<result.length;i++)
			result[i] = result[i].stripTags();
		
		return result;
	  },
	  evalScripts: function() {
		var elements = this.extractScripts();
		for(var i=0;i<elements.length;i++)
			eval(elements[i]);
	  },
	  escapeHTML: function() {
		var div = pimpas.DOM.createElement('div', null);
		var text = pimpas.DOM.createTextNode(this);
		pimpas.DOM.add(div, text);
		return this.getObjectValue(div);
	  },
	  unescapeHTML: function() {
		var div = pimpas.DOM.createElement('div', null);
		div.innerHTML = this.stripTags();
		return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
	  },
	  toArray: function() {
		return this.split('');
	  },
	  camelize: function() {
		var oStringList = this.split('-');
		if (oStringList.length == 1) return oStringList[0];
		  
		var camelizedString = this.indexOf('-') == 0
		  ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) 
		  : oStringList[0];
		  
		for (var i = 1, len = oStringList.length; i < len; i++) {
		  var s = oStringList[i];
		  camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
		}
		return camelizedString;
	  },
	  inspect: function() {
		return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'";
	  },
	  endsWith: function(cmp) {
		if(this.indexOf(cmp) < 0) return false;
		var posx = this.indexOf(cmp);
		return this.substring(posx) == cmp;
	  },
	  startsWith: function(cmp) {
		if(this.indexOf(cmp)<0) return false;
		var posx = this.indexOf(cmp);
		return this.substring(0, posx) == cmp;
	  }
	}
);pimpas.Filter = Class.create( );
pimpas.Extends(pimpas.Filter.prototype, pimpas.Object);
pimpas.Extends(pimpas.Filter.prototype, 
			   {
				   accept: function(obj) { }
			   }
);pimpas.Browser = Class.create( );
pimpas.Extends(pimpas.Browser, {
	name: null,
	isMozilla: false,
	isIE: false,
	isOpera: false,
	initialize: function() {
		if (document.recalc) {this.name = "ie"; this.isIE = true;}
		else if (window.__defineGetter__) {this.name = "gecko";this.isMozilla = true;}
		else if (window.opera){this.name = "opera"; this.isOpera = true;}
		else if (navigator.userAgent.match("Safari")){this.name = "safari"}
	}
}
);
pimpas.Browser.initialize( );pimpas.Listener = Class.create( );
pimpas.Extends(pimpas.Listener.prototype, pimpas.Object);
pimpas.Extends(pimpas.Listener.prototype,
	{
		callBack: function(obj, evt) {
			
		},
		initialize: function() {
			this.id = pimpas.globalID++;
			this.log = new pimpas.Log();
		}
	}
);

pimpas.ListenerSupport = Class.create( );

pimpas.Extends(pimpas.ListenerSupport.prototype, pimpas.Object);

pimpas.Extends(pimpas.ListenerSupport.prototype,
   {
	listeners: new Array(),
	initialize: function() {
		this.id = pimpas.globalID++;
		this.log = new pimpas.Log();
		this.listeners = new Array();
	},
	addListener: function(obj) {
		this.listeners.push(obj);
	},
	removeListener: function(obj) {
			this.listeners.remove(obj);								
	},
	clearListeners: function() {
		this.listeners = new Array();
	},
	callListeners: function() {
		var evt = arguments[0];
		var ar = new Array();
		ar.push(this);
		for(var i=0;i<arguments.length;i++) ar.push(arguments[i]);
		
		for(var i=0;i<this.listeners.length;i++)
			this.listeners[i].callBack.apply(this.listeners[i], ar);
		return evt;
	}
   }
);pimpas.Log = Class.create( );

pimpas.Extends(pimpas.Log.prototype, pimpas.Object);
pimpas.Extends(pimpas.Log.prototype, pimpas.ListenerSupport.prototype);
pimpas.Extends(pimpas.Log.prototype,
   {
		message: null,
		initialize: function() {
			this.message = new Array();
			pimpas.Log.add(this);
			this.id=pimpas.globalID++;
			this.listeners = new Array();
		},
		log: function(level, msg) {
			var obj = [level, msg, new Date(), this.log.caller];
			this.message.push(obj);
			this.callListeners(this.returnMessage(obj));
		},
		debug: function(msg) {
			this.log(pimpas.Log.DEBUG, msg);		
		},
		info: function(msg) {
			this.log(pimpas.Log.INFO, msg);
		},
		warning: function(msg) {
			this.log(pimpas.Log.WARN, msg);
		},
		error: function(msg) {
			this.log(pimpas.Log.ERROR, msg);
		},
		fatal: function(msg) {
			this.log(pimpas.Log.FATAL, msg);
		},
		flush: function() {
			var msg = this.message;
			if(arguments.length > 0)
				msg = arguments[0];
			var a = "";
			while(msg.length > 0)
				a += msg.shift().join("=>");
			return a;
		},
		flushByLevel: function(lvl) {
			var ar = new Array();
			for(var i=0;i<this.message.length;i++)
				if(this.message[i][0] == lvl)	
					ar.push(this.message[i]);
					
			return this.flush( ar );
		},
		pop: function() {
			if(this.message.length > 0) {
				var o = this.message.shift();
				return this.returnMessage(o);
			}
			
			return null;
		},
		returnMessage: function(o) {
				return {level: o[0], message: o[1], time: o[2], owner: o[3]};
		},
		popByLevel: function(lvl) {
			for(var i=0;i<this.message.length;i++) {
				if(this.message[i][0] == lvl)
					return this.returnMessage(this.message.remove(this.message[i]));		
			}
			return null;
		},
		hasMessage: function() {
			return this.message.length>0;
		},
		toSource: function() {
			return this.message;	
		},
		callListeners: function() {
			var ar = new Array();
			ar.push(this);
			
			for(var i=0;i<arguments.length;i++) ar.push(arguments[i]);
			
	 		for(var i=0;i<this.listeners.length;i++)
				this.listeners[i].callBack.apply(this.listeners[i], ar);
				
			for(i=0;i<pimpas.Log.globalListeners.length;i++)
				pimpas.Log.globalListeners[i].callBack.apply(pimpas.Log.globalListeners[i], ar);
		}
   }
);

pimpas.Extends(pimpas.Log, 
	{
		DEBUG: "[DEBUG]",
		INFO: "[INFO]",
		WARNING: "[WARNING]",
		ERROR: "[ERROR]",
		FATAL: "[FATAL]"
	}
);

pimpas.Extends(pimpas.Log,
	{
		instances: new Array(),
		add: function(obj) {
			this.instances.push(obj);
		},
		globalListeners: new Array(),
		addGlobalListener: function(l) {
			if(l instanceof pimpas.Listener)
				this.globalListeners.push(l);
		}
	}
);pimpas.FireBug = Class.create( );
pimpas.Extends(pimpas.FireBug, pimpas.Object);
pimpas.Extends(pimpas.FireBug,
	{
		installLogInConsole: function(  ) {
			var filter = (arguments.length > 0) ? arguments[0] : null;
			pimpas.Log.addGlobalListener( new pimpas.FireBug.LogListener(filter) );
		}
	}
);

pimpas.FireBug.LogListener = pimpas.Listener;
pimpas.Extends(pimpas.FireBug.LogListener.prototype,
   {
	    filter: null,
	    initialize: function(filter) {
			this.id = pimpas.globalID++;
			this.log = new pimpas.Log();
			this.filter = filter;
		},
		callBack: function(ref, obj) {
			if(this.filter != null)
				if(!this.filter.apply(obj)) return;
			var h,m,s,ss;
			h = obj.time.getHours();
			m = obj.time.getMinutes();
			s = obj.time.getSeconds();
			ss = obj.time.getMilliseconds();
			var msg = "["+h+":"+m+":"+s+":"+ss+"] LEVEL: "+obj.level+" => "+obj.message;
			try {
				if(obj.level == pimpas.Log.DEBUG)					
					console.debug(msg);
				else if(obj.level == pimpas.Log.INFO)
					console.info(msg);
				else if(obj.level == pimpas.Log.ERROR || obj.level == pimpas.Log.FATAL)
					console.error(msg);
				else
					console.warn(msg);
			} catch(e){}
		}
   }
);

pimpas.FireBug.initialize( );pimpas.Timer = Class.create( );

pimpas.Extends(pimpas.Timer.prototype, pimpas.Object);
pimpas.Extends(pimpas.Timer.prototype, 
	{
		timer: null,
		method: null,
		executing: false,
		isExecuting: function( ) {
			return this.executing;
		},
		ref: null,
		initialize: function(timer, method, ref) {
			this.timer = timer;
			this.method = method;
			this.ref = ref;
		},
		process: function() {
			if(!this.executing) return;
			this.stop( );
			this.method.call(this.ref);
		},
		go: function() {
			if(this.executing) return;
			this.executing = true;
			window.setTimeout(this.process.bind(this), this.timer);
		},
		stop: function() {
			if(!this.executing) return;
			this.executing = false;
		}
	}
);pimpas.Interval = Class.create( );
pimpas.Extends(pimpas.Interval.prototype, pimpas.Timer);
pimpas.Extends(pimpas.Interval.prototype, 
	{
		interval: null,
		initialize: function(timer, method, ref) {
			this.timer = timer;
			this.method = method;
			this.ref = ref;
		},
		process: function() {
			if(!this.executing) return;
			this.method.call(this.ref);
		},
		go: function() {
			if(this.executing) return;
			this.executing = true;
			this.interval = window.setInterval(this.process.bind(this), this.timer);
		},
		stop: function() {
			if(!this.executing) return;
			this.executing = false;
			window.clearInterval( this.interval );
		}
	}
);pimpas.DOM = Class.create( );
pimpas.Extends(pimpas.DOM, pimpas.Object);
pimpas.Extends(pimpas.DOM,
	{
		getElementsByClassName: function getElementsByClassName(strClassName, strTagName, oElm){
			var arrElements = (strTagName == "*" && document.all)? document.all : oElm.getElementsByTagName(strTagName);
			var arrReturnElements = new Array();
			strClassName = strClassName.replace(/\-/g, "\\-");
			var oRegExp = new RegExp("(^|\\s)" + strClassName + "(\\s|$)");
			var oElement;
			for(var i=0; i<arrElements.length; i++){
				oElement = arrElements[i];      
				if(oRegExp.test(oElement.className))
					arrReturnElements.push(oElement);
			}
			return (arrReturnElements);
		},
		getElement: function(el) {
			var backup = el;
			if(typeof el == "string")
				el = document.getElementById(el);
			if(el == null && typeof backup == 'string')
				// try by form reference
				return this.getElementByFormReference(backup);
			return el;
		},
		getElementByFormReference: function(name) {
			// try looking for all form elements
			var forms = document.getElementsByTagName('form');
			var el = null;
			for(var i=0;i<forms.length;i++)
				for(var j=0;j<forms[i].elements.length;j++)
					if(forms[i].elements[j].name == name) {
						el = forms[i].elements[j];
						break;
					}
			return el;
		},
		convertToNodeList: function(el) {
			el = this.getElement(el);
			if(!(el instanceof NodeList)) {
				var frm = this.getParentForm(el);
				el = frm.elements[el.name];
			}				
			return el;
		},
		getObjectValue: function(el, convertToNode) {
			el = this.getElement(el);
			if(!this.isDefined(convertToNode)) convertToNode = true;
			if(this.isInput(el) || this.isTextArea(el)) {
				if(this.isRadio(el)) {
					if(convertToNode) {
						if(pimpas.Browser.isIE)
							el = this.getParentForm(el).elements[el.name];
						else
							el = this.convertToNodeList(el);
					}
					var value = new Array();
					var j = 0;
					if(el.length == undefined) 
						return (el.checked) ? el.value : null;
					for(var i=0;i<el.length;i++)
						if(el[i].checked)
							value[j++] = el[i].value;
					return value;
				} else if(this.isCheckbox(el)) {
					if(convertToNode) {
						if(pimpas.Browser.isIE)
							el = this.getParentForm(el).elements[el.name];
						else
							el = this.convertToNodeList(el);
					}
					var j = 0;
					if(el.length == undefined)
						return (el.checked) ? el.value : null;
					value = [];
					for(var i=0;i<el.length;i++)
						if(el[i].checked)
							value[j++] = el[i].value;
					return value;
				} else
					return el.value;
			}
			else if(this.isSelect(el)) {
				if(this.isMultipleSelect(el)) {
					var values = [];
					var j = 0;
					for(var i=0;i<el.options.length;i++)
						if(el.options[i].selected) values[j++] = el.options[i].value;
					return values;
				} else {
					var indx = el.selectedIndex;
					return el.options[indx].value;
				}
			}
			return el.innerHTML;
		},
		setObjectValue: function(el, value) {
			el = this.getElement(el);
			if(this.isInput(el) || this.isTextArea(el)) {
				if(this.isRadio(el)) {
					if(pimpas.Browser.isIE)
						el = this.getParentForm(el).elements[el.name];
					else
						if(!(el instanceof NodeList)) {
							var frm = this.getParentForm(el);
							el = frm.elements[el.name];
						}
					if(value != null)
						value = value.split(" ").join().split(",");
					else return;
					for(var i=0;i<el.length;i++)
						el[i].checked = false;
					for(var i=0;i<el.length;i++)
						if(el[i].value == value) {
							el[i].checked = true;
							break;
						}
				} else if(this.isCheckbox(el)) {
					if(pimpas.Browser.isIE)
						el = this.getParentForm(el).elements[el.name];
					else
						if(!(el instanceof NodeList)) {
							var frm = this.getParentForm(el);
							el = frm.elements[el.name];
						}
					if(value != null)
						value = value.split(" ").join().split(",");
					else return;
					// selectOne?! Boolean?!
					if(!(el instanceof NodeList)) {
						var v = value[0];
						el.checked = (v=='true') ? true : false;
						return;
					}
					
					for(var i=0;i<el.length;i++) el[i].checked = false;
					for(var i=0;i<value.length;i++)
						for(var j=0;j<el.length;j++)
							if(el[j].value == value[i]) el[j].checked = true;
				} else {
					if(pimpas.Browser.isIE)
						el.setAttribute("value", value);
					else
						el.value = value;
				}
			}
			else if(this.isSelect(el)) {
				if(this.isMultipleSelect(el)) {
					if(value != null)
						value = value.split(" ").join().split(",");
					else return;
					this.clearSelectedOptions(el);
					for(var i=0;i<value.length;i++)
						for(var j=0;j<el.options.length;j++)
							if(el.options[j].value == value[i]) el.options[j].selected = true;
				} else
					for(var i=0;i<el.options.length;i++)
						if(el.options[i].value == value) {
							el.selectedIndex = i;
							return;
						}
				return;
			} else {
				try {
					el.innerHTML = value;
				} catch(e) {
					// ie, dont change TABLE, THEAD, TFOOT, TR values, only for readOnly
					// so, burn in hell IE, we hate u!
				}
			}
		},
		isInput: function(el) {
			return this.getElement(el).tagName == "INPUT";	
		},
		isSelect: function(el) {
			return this.getElement(el).tagName == "SELECT";	
		},
		isMultipleSelect: function(el) {
			return this.isSelect(this.getElement(el)) && this.getElement(el).getAttribute("multiple") == "multiple" ||
				this.getElement(el).getAttribute("multiple") == "true";
		},
		isTextArea: function(el) {
			return this.getElement(el).tagName == "TEXTAREA";	
		},
		isButton: function(el) {
			return this.isInput(this.getElement(el)) && this.getElement(el).type == "button";	
		},
		isSubmit: function(el) {
			return this.isInput(this.getElement(el)) && this.getElement(el).type == "submit";	
		},
		isRadio: function(el) {
			return this.isInput(this.getElement(el)) && this.getElement(el).type == "radio";
		},
		isCheckbox: function(el) {
			return this.isInput(this.getElement(el)) && this.getElement(el).type == "checkbox";
		},
		isInputHidden: function(el) {
			return this.isInput(this.getElement(el)) && this.getElement(el).type == "hidden";
		},
		isScript: function(el) {
			return this.getElement(el).tagName == 'SCRIPT';
		},
		isStyle: function(el) {
			return this.getElement(el).tagName == 'STYLE';
		},
		isForm: function(el) {
			return this.getElement(el).tagName == 'FORM';	
		},
		isVisible: function(el) {
			el = this.getElement(el);
			return (this.getStyle(el, "visibility") != 'hidden' && this.getStyle(el, "display") != 'none') || (this.getStyle(el, "visibility") != "hidden" && this.getStyle(el, "visibility") != '');
		},
		isDisabled: function(el) {
			el = this.getElement(el);
			return el.getAttribute("disabled") != null && el.getAttribute("disabled").toString()=="true";
		},
		isReadOnly: function(el) {
			el = this.getElement(el);
			return el.getAttribute("readOnly")=="true";
		},
		toDisable: function() {
			var el = null;
			for(var i=0;i<arguments.length;i++) {
				el = this.getElement(arguments[i]);
				if(this.isDisabled(el)) return;
				el.setAttribute("disabled", "true");
			}
		},
		toEnable: function() {
			var el = null;
			for(var i=0;i<arguments.length;i++) {
				el = this.getElement(arguments[i]);
				if(!this.isDisabled(el)) return;
				el.removeAttribute("disabled");
			}
		},
		toReadWrite: function() {
			var el = null;
			for(var i=0;i<arguments.length;i++) {
				el = this.getElement(arguments[i]);
				if(!this.isReadOnly(el)) continue;
				el.removeAttribute("readOnly");
			}
		},
		toReadOnly: function() {
			var el = null;
			for(var i=0;i<arguments.length;i++) {
				el = this.getElement(arguments[i]);
				if(this.isReadOnly(el)) continue;
				el.setAttribute("readOnly", "true");
			}
		},
		toVisible: function() {
			var el = null;
			for(var i=0;i<arguments.length;i++) {
				el = this.getElement(arguments[i]);
				if(this.isVisible(el)) continue;
				var styles = new Array();
				styles["display"] = "block";
				styles["visibility"] = "visible";
				
				this.setStyle( el, styles );
			}
		},
		toHidden: function() {
			var el = null;
			for(var i=0;i<arguments.length;i++) {
				el = this.getElement(arguments[i]);
				if(!this.isVisible(el)) continue;
				var styles = new Array();
				styles["display"] = "none";
				styles["visibility"] = "hidden";
				this.setStyle( el, styles);
			}
		},
		toggleVisibility: function() {
			var el = null;
			for(var i=0;i<arguments.length;i++) {
				el = this.getElement(arguments[i]);
				(this.isVisible(el)) ? this.toHidden(el) : this.toVisible(el);
			}
		},
		remove: function(el) {
			el = this.getElement(el);
			el.parentNode.removeChild(el);
		},
		add: function(parent, el) {
			parent = this.getElement(parent);
			el = this.getElement(el);
			parent.appendChild(el);
		},
		insertBefore: pimpas.insertBefore,
		insertAfter: function(parent, newNode, refNode) {
			parent = this.getElement(parent);
			refNode = this.getElement(refNode);
			parent.insertAfter(newNode, refNode);
		},
		update: function(el, html) {
			el = this.getElement(el);
			try {
				el.innerHTML = html.stripScripts();
				var timer = new pimpas.Timer(10, function() {html.evalScripts();}, null);
				timer.go();
			} catch(e) {
				// simple setvalue
				this.setObjectValue( el, html );
			}
		},
		getClassNames: function(el) {
			el = this.getElement(el);
			return el.className.split(" ");
		},
		hasClassName: function(el, clazz) {
			el = this.getElement(el);
			var clazzs = this.getClassNames(el);
			for(var i=0;i<clazzs.length;i++)
				if(clazzs[i] == clazz) return true;
			return false;
		},
		addClassName: function(el, clazz) {
			el = this.getElement(el);
			if(this.hasClassName(el, clazz)) return;
			el.className += " "+clazz;
		},
		setClassName: function(el, clazz) {
			el = this.getElement(el);
			el.className = clazz;
		},
		resetClassName: function(el) {
			el = this.getElement(el);
			el.className = "";
		},
		removeClassName: function(el, clazz) {
			el = this.getElement(el);
			if(!this.hasClassName(el, clazz)) return;
			
			var clazzs = this.getClassNames(el);
			var newClazzs = new Array();
			for(var i=0;i<clazzs.length;i++) {
				if(clazzs[i] == clazz) continue;
				newClazzs.push( clazzs[i] );
			}
			this.resetClassName(el);
			while(newClazzs.length>0) this.addClassName(newClazzs.shift());
		},
		isEmpty: function(el) {
			return this.getElement(el).innerHTML.match(/^\s*$/);
		},
	    getStyle: function(el, style) {
			el = this.getElement(el);
			var value = el.style[style.camelize()];
			
			if (!value) {
			  if (document.defaultView && document.defaultView.getComputedStyle) {
				var css = document.defaultView.getComputedStyle(el, null);
				value = css ? css.getPropertyValue(style) : null;
			  } else if (el.currentStyle) {
				value = el.currentStyle[style.camelize()];
			  }
			}
			if (pimpas.Browser.isOpera && ['left', 'top', 'right', 'bottom'].have(style))
			  if (this.getStyle(el, 'position') == 'static') value = 'auto';
		
			return value == 'auto' ? null : value;
		},
  	    setStyle: function(el, style) {
			el = this.getElement(el);
			for (name in style)
				try {
					el.style[name.camelize()] = style[name];
				} catch(e) {};
			
	    },
		getHeight: function(el) {
			return this.getElement(el).offsetHeight; 
		},
		scrollTo: function(el) {
			el = this.getElement(el);
			var x = el.x ? el.x : el.offsetLeft,
				y = el.y ? el.y : el.offsetTop;
			window.scrollTo(x, y);
		},
		createElement: function(type, id) {
			var el = document.createElement(type);
			if(id!=null) el.setAttribute("id", id);
			return el;
		},
		createTextNode: function(text) {
			var el = document.createTextNode(text);
			return el;
		},
		havChild: function(parent, child) {
			parent = this.getElement(parent);
			child = this.getElement(child);
			return parent.childNodes.have(child);
		},
		replace: function(old, newOne) {
			old = this.getElement(old);
			newOne = this.getElement(newOne);
			old.parentNode.replace( old, newOne );
		},
		createOption: function(text, value) {
			return new Option(text, value);
		},
		getOption: function(el, value) {
			el = this.getElement(el);
			if(!this.isSelect(el)) return;
			for(var i=0;i<el.options.length;i++)
				if(el.options[i].value == value) return el.options[i];
			return null;
		},
		addOption: function(el, text, value) {
			el = this.getElement(el);
			if(!this.isSelect(el)) return;
			el.options[el.options.length] = this.createOption(text, value);
		},
		removeOption: function(el, value) {
			el = this.getElement(el);
			if(!this.isSelect(el)) return;
			op = this.getOption(el, value);
			if(op != null) {
				var a = [];
				var j = 0;
				for(var i=0;i<el.options.length;i++)
					if(el.options[i].value != value) a[j++] = el.options[i];
				el.options.length = 0;
				for(var i=0;i<a.length;i++) this.addOption(el, a[i].text, a[i].value);
				a = null;
			}
		},
		clearAllOptions: function(el) {
			el = this.getElement(el);	
			if(!this.isSelect(el)) return;
			
			el.options.length = 0;
		},
		clearSelectedOptions: function(el) {
			el = this.getElement(el);
			if(!this.isSelect(el)) return;
			if(this.isMultipleSelect(el))
				for(var i=0;i<el.options.length;i++)
					el.options[i].selected = false;
			else
				el.selectedIndex = 0;
		}
	}
);

pimpas.Extends(pimpas.DOM, 
	{
		focus: function(el) {
			el = this.getElement(el);
			try {
				el.focus( );
			} catch(e) {
				
			}
		},
		select: function(el) {
			el = this.getElement(el);
			try {
				el.select( );	
			} catch(e) {
				
			}
		},
		isField: function(el) {
			el = this.getElement(el);
			return (this.isSelect(el) || (this.isInput(el) && !this.isButton(el) && !this.isSubmit(el)) || this.isTextArea(el));
		},
		isSerializable: function(el) {
			el = this.getElement(el);
			return (this.isSelect(el) || this.isInput(el) || this.isTextArea(el));
		},
		serialize: function(el, convert) {
			el = this.getElement(el);
			var ar = new Array();
			var value = this.getObjectValue(el, convert);
			if(this.isRadio(el) || this.isCheckbox(el) || this.isMultipleSelect(el))
				if(value == null || value.length == 0) return null;
			
			ar.push((el.id) ? el.id : el.name);
			ar.push(encodeURIComponent(value));
			return ar;
		},
		getParentForm: function(el) {
			el = this.getElement(el);
			while(el != null && !this.isForm(el))
				el = el.parentNode;
			return el;
		},
		serializeForm: function(el, filter) {
			el = this.getElement(el);
			if(!this.isForm(el)) el = this.getParentForm(el);
			var ser = new Array();
			var notFound = false;
			var filters = new Array();
			if(pimpas.DOM.isDefined(filter) && filter instanceof pimpas.Filter)
				filters.push(filter);
			var accepted = true;
			var ft = null;
			var tmp = null;
			for(var i=0;i<el.elements.length;i++) {
				if(this.isSerializable(el.elements[i])) {
					// execute all listeners
					accepted = true;
					while(filters.length > 0) {
						ft = filters.pop();
						try {
							accepted = ft.accept( el.elements[i] );
						} catch(e) {
							accepted = false;	
						}
						if(!accepted) break;
					}
					if(accepted) {
						tmp = this.serialize(el.elements[i], false);
						if(tmp != null)
							ser.push(tmp);
					}
				}
			}
			
			var str = new Array();
			while(ser.length>0)
				str.push(ser.shift( ).join("="));

			return str.join("&");
		}
	}
);

pimpas.Extends(pimpas.DOM,
	{
		getDimensions: function(el) {
			el = this.getElement(el);
			if(this.isVisible(el))
			  return {width: el.offsetWidth, height: el.offsetHeight};
			
			var els = el.style;
			var originalVisibility = els.visibility;
			var originalPosition = els.position;
			els.visibility = 'hidden';
			els.position = 'absolute';
			els.display = '';
			var originalWidth = el.clientWidth;
			var originalHeight = el.clientHeight;
			els.display = 'none';
			els.position = originalPosition;
			els.visibility = originalVisibility;
			return {width: originalWidth, height: originalHeight};    
		},
		getRealOffset: function(el) {
			el = this.getElement(el);
			var valueT = 0, valueL = 0;
			do {
				valueT += el.scrollTop  || 0;
				valueL += el.scrollLeft || 0; 
				el = el.parentNode;
			} while (el);
			
			return [valueL, valueT];
		},
		getCumulativeOffset: function(el) {
			el = this.getElement(el);
			var valueT = 0, valueL = 0;
			do {
				valueT += el.offsetTop  || 0;
				valueL += el.offsetLeft || 0;
				el = el.offsetParent;
			} while (el);
			
			return [valueL, valueT];
		},
		getPositionedOffset: function(el) {
			el = this.getElement(el);
			var valueT = 0, valueL = 0;
			do {
				valueT += el.offsetTop  || 0;
				valueL += el.offsetLeft || 0;
				el = el.offsetParent;
				if (el) {
					p = this.getStyle(el, 'position');
					if (p == 'relative' || p == 'absolute') break;
				}
			} while (el);
			
			return [valueL, valueT];
		},
		getOffsetParent: function(el) {
			el = this.getElement(el);
			if (el.offsetParent) return el.offsetParent;
			if (el == document.body) return el;
			
			while ((el = el.parentNode) && el != document.body)
				if (this.getStyle(el, 'position') != 'static')
					return el;
			
			return document.body;
		},
		clone: function(source, target) {
			source = this.getElement(source);
			target = this.getElement(target);
			
			var styles = new Array();
			
			styles["position"]	 = 'absolute';
			var offsets 		= this.getCumulativeOffset(source);
			styles["top"] 		= offsets[1] + 'px';
			styles["left"]   	= offsets[0] + 'px';
			styles["width"]  	= source.offsetWidth + 'px';
			styles["height"] 	= source.offsetHeight + 'px';
			
			pimpas.DOM.setStyle( target, styles );
		},
		setCursor: function(el, c) {
			el = this.getElement(el);
			var styles = new Array();
			styles["cursor"] = c;
			this.setStyle( el, styles );
		},
		within: function(el1, el2) {
			var targetPosition = pimpas.DOM.getCumulativeOffset(el2);
			var sourcePosition = pimpas.DOM.getCumulativeOffset(el1);
			var targetDimension = pimpas.DOM.getDimensions(el2);
			var sourceDimension = pimpas.DOM.getDimensions(el1);
			var styles = new Array();
			styles["border"] = "";
			if(sourcePosition[0] > targetPosition[0] && sourcePosition[1] > targetPosition[1]) {
				x = targetPosition[0];
				y = targetPosition[1];
				var horizontal = ((sourcePosition[0] + el1.offsetWidth) - x) / 
					el2.offsetWidth;
				var vertical = ((sourcePosition[1] + el1.offsetHeight) - y) / 
					el1.offsetHeight;
				
				return (horizontal > 0 && horizontal < 1 && ((el1.offsetHeight + sourcePosition[1]) < (el2.offsetHeight + targetPosition[1])));
			}
		}
  	}
);

pimpas.Extends(pimpas.DOM,
			   {
				   isDefined: function(ar) {
					    try {
							return ar != null && ar != undefined;   
						} catch(e) { return false; };
				   }
			   }
);
// drag-drop
pimpas.Extends(pimpas.DOM,
   {
	   enableDrag: function(el) {
			el = this.getElement(el);
			if(this.isDragAble(el)) return;
			pimpas.DOM.Event.addListener( el, pimpas.DOM.Event.MOUSEDOWN, pimpas.DOM.dragInit, false ); 
			pimpas.DOM.dragDropChangeCursor( el, true );			
	   },
	   dragDropChangeCursor: function(el, onoroff) {
	   		el = this.getElement(el);
			if(pimpas.DOM.isDefined(onoroff) && onoroff == true)
				pimpas.DOM.setCursor( el, pimpas.DOM.Cursors.MOVE );
			else
				pimpas.DOM.setCursor( el, pimpas.DOM.Cursors.DEFAULT );
	   },
	   dragInit: function(e) {
			e = pimpas.DOM.Event.fixEvent(e);
			var el = pimpas.DOM.Event.getElement(e);
			var styles = new Array();
			
			el.setAttribute("oldBottom", pimpas.DOM.getStyle( el, 'bottom' ));
			el.setAttribute("oldRight", pimpas.DOM.getStyle( el, 'right' ));
			el.setAttribute("oldPosition", pimpas.DOM.getStyle( el, 'position' ));
			el.setAttribute("oldZIndex", pimpas.DOM.getStyle( el, 'zIndex' ));
			
			if(pimpas.DOM.getStyle( el, 'bottom' ) == null || pimpas.DOM.getStyle( el, 'bottom' ) == '')
				styles["bottom"] = "0px";
			if(pimpas.DOM.getStyle( el, 'right' ) == null || pimpas.DOM.getStyle( el, 'right' ) == '')
				styles["right"] = "0px";
			styles["position"] = "relative";
			styles["zIndex"] = "99999999999";
			
			pimpas.DOM.setStyle(el, styles);
				
		    pimpas.DOM.Event.removeListener( el, pimpas.DOM.Event.MOUSEDOWN, pimpas.DOM.dragInit, false ); 
			
			pimpas.DOM.Event.addListener( document, pimpas.DOM.Event.MOUSEMOVE, pimpas.DOM.dragStart, false );
			pimpas.DOM.Event.addListener( document, pimpas.DOM.Event.MOUSEUP, pimpas.DOM.dragEnd, false );
			
			el.setAttribute("Drag-LastMouseX", e.clientX);
			el.setAttribute("Drag-LastMouseY", e.clientY);
			el.setAttribute("DragAble", "true");
	   },
	   dragStart: function(e) {
		    e = pimpas.DOM.Event.fixEvent(e);
			var el = pimpas.DOM.Event.getElement(e);
			var ey	= e.clientY;
			var ex	= e.clientX;
			var y = parseInt(pimpas.DOM.getStyle(el, "bottom"));
			var x = parseInt(pimpas.DOM.getStyle(el, "right"));
			var nx = x + ((ex - el.getAttribute("Drag-LastMouseX")) * -1);
			var ny = y + ((ey - el.getAttribute("Drag-LastMouseY")) * -1);
			
			var styles = new Array();
			
			styles["right"] = nx + "px";
			styles["bottom"] = ny + "px";
			
			pimpas.DOM.setStyle( el, styles );
			
			el.setAttribute("Drag-LastMouseX", ex);
			el.setAttribute("Drag-LastMouseY", ey);
	   },
	   dragEnd: function(e) {
		    e = pimpas.DOM.Event.fixEvent(e);
			var el = pimpas.DOM.Event.getElement(e);
			pimpas.DOM.disableDrag(el);
	   },
	   isDragAble: function(el) {
		   el = this.getElement(el);
		   return el.getAttribute("DragAble")=="true";
	   },
	   disableDrag: function(el) {
		    el = this.getElement(el);
			if(!this.isDragAble(el)) return;
			
			pimpas.DOM.Event.removeListener( document, pimpas.DOM.Event.MOUSEMOVE, pimpas.DOM.dragStart, false );
			pimpas.DOM.Event.removeListener( document, pimpas.DOM.Event.MOUSEUP, pimpas.DOM.dragEnd, false );
			pimpas.DOM.dragDropChangeCursor( el, false );			
			el.removeAttribute("Drag-LastMouseX");
			el.removeAttribute("Drag-LastMouseY");
			

			// recover
			var styles = new Array();
			styles["bottom" ] 		= el.getAttribute("oldBottom");
			styles["right" ] 		= el.getAttribute("oldRight");
			styles["position" ] 	= el.getAttribute("oldPosition");
			styles["zIndex" ] 		= el.getAttribute("oldZIndex");
			
			//pimpas.DOM.setStyle( el, styles );
			//alert(pimpas.DOM.getStyle( el, 'position' ));
			
			el.removeAttribute("oldBottom");
			el.removeAttribute("oldRight");
			el.removeAttribute("oldPosition");
			el.removeAttribute("oldZIndex");
			
	   },
	   switchDragAble: function(el) {
		   el = this.getElement(el);
		   (!this.isDraAble(el)) ? this.enableDrag(el) : this.disableDrag(el);
	   }
   }
);

// filters
pimpas.DOM.Filters = Class.create( );
pimpas.Extends(pimpas.DOM.Filters,
	{
		applyOpacity: function(el, n) {
			el = pimpas.DOM.getElement( el );
			var styles = new Array();
			if(pimpas.Browser.isMozilla)
				styles["MozOpacity"] = n;
			else if(pimpas.Browser.isIE)
				styles["filter"] = "alpha(opacity="+(n*100)+")";
			else if(pimpas.Browser.isOpera)
				styles["opacity"] = n;
				
			pimpas.DOM.setStyle( el, styles );
		}
	}
);


// cursors
pimpas.DOM.Cursors = Class.create( );
pimpas.Extends(pimpas.DOM.Cursors,
	{
		DEFAULT: 		'default',
		CROSSHAIR: 		'crosshair',
		ERESIZE: 		'e-resize',
		HAND: 			'hand',
		HELP: 			'help',
		MOVE: 			'move',
		NRESIZE: 		'n-resize',
		NERESIZE:		'ne-resize',
		NWRESIZE: 		'nw-resize',
		SRESIZE: 		's-resize',
		SERESIZE: 		'se-resize',
		SWRESIZE: 		'sw-resize',
		TEXT: 			'text',
		WRESIZE: 		'w-resize',
		WAIT:			'wait'
	}
);

pimpas.Extends(pimpas.DOM,
	{
		clone: function(source) {
			source = this.getElement(source);
			var target = pimpas.DOM.createElement(source.tagName);
			for(var prop in source) {
				try {
					target[prop] = source[prop];	
				} catch(e){}
			}
			return target;
		}
	}
);

pimpas.DOM.initialize();pimpas.DOM.Event = Class.create( );
pimpas.Extends(pimpas.DOM.Event, pimpas.Object);
pimpas.Extends(pimpas.DOM.Event, pimpas.ListenerSupport.prototype);
// listener
pimpas.DOM.Event.Listener = Class.create( );
pimpas.Extends(pimpas.DOM.Event.Listener.prototype, pimpas.Listener.prototype);
pimpas.Extends(pimpas.DOM.Event.Listener.prototype, 
   {
	   observer: null,
	   eventName: null,
	   element: null,
	   useCapture: null,
	   initialize: function(o, en, e, u) {
			this.id = pimpas.globalID++;
			this.log = new pimpas.Log();
			this.observer = o;
			this.eventName = en;
			this.element = pimpas.DOM.getElement( e );
			this.useCapture = u;
	   },
	   callBack: function(event) {
	   },
	   toString: function() {
			return "[DOM-EVENT-LISTENER]";   
	   }
   }
);
pimpas.Extends(pimpas.DOM.Event,
   {
	initialize: function() {
		this.id = pimpas.globalID++;
		this.log = new pimpas.Log();
		this.listeners = new Array();
	},
	fixEvent: function(e) {
		return e || event || window.event;
	},
	getElement: function(event) {
		event = this.fixEvent(event);
		return (event.target || event.srcElement);   
	},
	getKeyPressed: function(event) {
		event = this.fixEvent(event);
		return (event.keyCode || event.which);
	},
	isLeftClick: function(event) {
		event = this.fixEvent(event);
		return (((event.which) && (event.which == 1)) ||
				((event.button) && (event.button == 1)));
	},
	isRightClick: function(event) {
		event = this.fixEvent(event);
		return (((event.which) && (event.which == 2)) ||
				((event.button) && (event.button == 2)));
	},
	pointerX: function(event) {
		event = this.fixEvent(event);
		return event.pageX || (event.clientX + 
		  (document.documentElement.scrollLeft || document.body.scrollLeft));
	},
	pointerY: function(event) {
		event = this.fixEvent(event);
		return event.pageY || (event.clientY + 
		  (document.documentElement.scrollTop || document.body.scrollTop));
	},
	stop: function(event) {
		event = this.fixEvent(event);
		if (event.preventDefault) { 
		  event.preventDefault(); 
		  event.stopPropagation(); 
		} else {
		  event.returnValue = false;
		  event.cancelBubble = true;
		}
	},
	addListener: function(element, eventName, observer, useCapture) {
		var l = new pimpas.DOM.Event.Listener(observer, eventName, element, useCapture);
		
		this.registerBrowserListener( l );
		this.listeners.push( l );
	},
	registerBrowserListener: function( l ) {
		if(l.element.addEventListener)
	    	l.element.addEventListener(l.eventName, l.observer, l.useCapture);
		else if(l.element.attachEvent)
	    	l.element.attachEvent('on' + l.eventName, l.observer);
		else
			throw "Not implemented Yet";
	},
	unRegisterBrowserListener: function( l ) {
		
		if(l.element.removeEventListener)
			l.element.removeEventListener( l.eventName, l.observer, l.useCapture );
		else if(l.element.detachEvent)
			l.element.detachEvent('on' + l.eventName, l.observer);
		else
			throw "Not implemented Yet";
	},
	callListeners: function() {
		
	},
	removeListener: function(el, eventName, observer) {
		el = pimpas.DOM.getElement( el );
		var l = null;
		for(var i=0;i<this.listeners.length;i++)
			if(this.listeners[i].element == el &&
				this.listeners[i].eventName == eventName &&
				this.listeners[i].observer == observer) {
				l = this.listeners[i];
				break;
			}
		if(l != null) {
			this.listeners.remove( l );
			this.unRegisterBrowserListener( l );
		}
	 },
	 CLICK: "click",
	 FOCUS: "focus",
	 MOUSEMOVE: "mousemove",
	 KEYPRESS: "keypress",
	 KEYUP: "keyup",
	 KEYDOWN: "keydown",
	 BLUR: "blur",
	 SUBMIT: "submit",
	 MOUSEOVER: "mouseover",
	 MOUSEOUT: "mouseout",
	 MOUSEDOWN: "mousedown",
	 MOUSEUP: "mouseup",
	 LOAD: "load",
	 UNLOAD: "unload"
   }
);

pimpas.DOM.Event.initialize( );pimpas.HTTPRequest = Class.create( );

pimpas.Extends(pimpas.HTTPRequest.prototype, pimpas.Object);
pimpas.HTTPRequest.Listener = pimpas.Listener;

pimpas.HTTPRequest.ListenerSupport = Class.create();
pimpas.Extends(pimpas.HTTPRequest.ListenerSupport.prototype, pimpas.ListenerSupport.prototype);
pimpas.Extends(pimpas.HTTPRequest.ListenerSupport.prototype, {
	callListeners: function() {
		var evt = arguments[0];
		var ar = new Array();
		ar.push(this);
		
		this.log.info("Calling HTTPRequest listeners for event ["+evt+"]");
		
		for(var i=0;i<arguments.length;i++) ar.push(arguments[i]);
		
 		for(var i=0;i<this.listeners.length;i++)
			this.listeners[i].callBack.apply(this.listeners[i], ar);
			
		for(i=0;i<pimpas.HTTPRequest.globalListeners.length;i++)
			pimpas.HTTPRequest.globalListeners[i].callBack.apply(pimpas.HTTPRequest.globalListeners[i], ar);
		
		return evt;
	}
   }
);

pimpas.Extends(pimpas.HTTPRequest.prototype, pimpas.HTTPRequest.ListenerSupport.prototype);

pimpas.Extends(pimpas.HTTPRequest.prototype, 
 {
	url: null,
	setUrl: function(t) {
		this.url = t;	
	},
	getUrl: function() {
		return this.url;	
	},
	pooled: false,
	isPooled: function() {
		return this.pooled;
	},
	setPooled: function(p) {
		this.pooled = p;
	},
	async: null,
	setAsync: function(a) {
		this.async = a;
	},
	getAsync: function() {
		return this.async;
	},
	status: null,
	queueMode: null,
	listeners: null,
	transport: null,
	requestMethod: null,
	formString: null,
	setRequestMethod: function(t) {
		this.requestMethod = t;	
	},
	getRequestMethod: function() {
		return this.requestMethod;
	},
	userName: null,
	passWord: null,
	parameters: null,
	maxTime: null,
	getMaxTime: function( ) {
		return this.maxTime;
	},
	setMaxTime: function(t) {
		this.maxTime = t;
	},
	timer: null,
	lastCall: null,
	addParameter: function(k,v) {
		this.parameters.push([k,v]);
	},
	headers: null,
	processLife: function( ) {
		if(pimpas.HTTPRequest.isFinished(this.status))
			// just go away
			return;
		// check lastCall
		var t = new Date().getTime();
		if( (t - this.lastCall) > this.maxTime) {
			this.log.log(pimpas.Log.INFO, "Object "+this.id+" is possible dead. Killing Request...");
			this.abort( );
			return;
		}
		
		this.log.info("HttpRequest Object with ID ["+this.id+"] its not dead! Give it another chance.");
		this.timer.go( );
	},
	cleanUp: function( ) {
		this.parameters = new Array();
		this.clearListeners( );
		this.async = true;
		this.url = null;
		this.transport = null;
		this.userName = null;
		this.passWord = null;
		this.headers = new Array();
		this.log = new pimpas.Log();
		this.maxTime = pimpas.HTTPRequest.defaultTime;
		this.pooled = false;
		this.formString = null;
		this.lastCall = null;
		this.queueMode = false;
		this.status = this.callListeners(pimpas.HTTPRequest.events.unInitialized);
	},
	initialize: function(  ) {
		this.id = pimpas.globalID++;
		this.cleanUp( );
		this.requestMethod = pimpas.HTTPRequest.methods.GET;
		this.log.log(pimpas.Log.DEBUG, 'Creating Object with ID '+this.id);
		pimpas.HTTPRequest.requests.push(this);
	},
	initTransport: function( ) {
		this.timer = new pimpas.Timer(this.maxTime, this.processLife, this);
   		this.transport = pimpas.HTTPRequest.createTransport();
		this.status = this.callListeners(pimpas.HTTPRequest.events.onCreate);
		this.log.log(pimpas.Log.DEBUG, 'Transport Created for Object '+this.id);
	},
	sendForm: function( obj, filter ) {
		this.formString = pimpas.DOM.serializeForm( obj, filter );
		var frm = pimpas.DOM.getParentForm( obj );
		this.setUrl( frm.action );
		this.setRequestMethod( frm.method==pimpas.HTTPRequest.methods.POST ? pimpas.HTTPRequest.methods.POST : pimpas.HTTPRequest.methods.GET);
	},
	processParameters: function( ) {
		var parameters = new Array();
		var el = null;
		while(this.parameters.length > 0) {
			el = this.parameters.shift();
			parameters.push(el.join('='));
		}
		
		var pString = (this.formString!=null) ? this.formString +"&" : "";
		pString += parameters.join('&');
		
		return pString;
	},
	validate: function( ) {
		return true;
	},
	processHeaders: function( ) {
		if(this.requestMethod == pimpas.HTTPRequest.methods.POST)
			this.headers.push(['Content-type', 'application/x-www-form-urlencoded']);
			
		this.headers.push(['X-Requested-With', 'XMLHttpRequest']);
		this.headers.push(['Pimpas-Framework-JS-Version', pimpas.version]);
	},
	request: function() {
		if(this.getUrl( ) == null)
			throw new UrlNotFoundException();
			
		// already running?!
		if(this.status != pimpas.HTTPRequest.events.unInitialized)
			// already running
			throw new RequestAlreadyRunning();
		
		if(this.transport == null) this.initTransport( );	
			
		if(!this.validate()) {
			this.log.info("[HTTPREQUEST] Error in validate! Returning...");	
			return;
		}
		
		// headers
		this.processHeaders( );
		
		var pString = this.processParameters( );
		
		if(this.requestMethod == pimpas.HTTPRequest.methods.GET && pString.length > 0)
			this.setUrl(this.getUrl() + (this.getUrl( ).match(/\?/) ? '&' : '?') + pString);
			
		if(this.async)
			this.transport.onreadystatechange = this.onReadyStateChange.bind(this);
		
		this.transport.open(this.getRequestMethod(), this.getUrl( ), this.async, this.userName, this.passWord);
		
		for(var i=0;i<this.headers.length;i++)
			this.transport.setRequestHeader(this.headers[i][0], this.headers[i][1]);

		try {
			pimpas.HTTPRequest.activeRequests++;
			this.log.log(pimpas.Log.DEBUG, 'Executing Request for Object ['+this.id+'] [URL]: '+this.getUrl()+", [PARAMETERS]: "+pString+", [ASYNC]: "+this.async);
			this.status = this.callListeners(pimpas.HTTPRequest.events.onInitialize);
			this.transport.send((this.getRequestMethod() == pimpas.HTTPRequest.methods.POST) ? pString : null);
			if(this.async)
				this.timer.go( );
			else
				this.onReadyStateChange( );
		} catch(e) {
			pimpas.HTTPRequest.activeRequests--;
			if(this.timer.isExecuting())
				this.timer.stop( );
			this.log.log(pimpas.Log.ERROR, e);
			if(pimpas.Browser.isIE)				
				this.transport.onreadystatechange = pimpas.emptyFunction;
			
			if(this.async)
				this.status = this.callListeners(pimpas.HTTPRequest.events.onError, e);
			else
				throw e;
		}
	},
	onReadyStateChange: function( ) {
		// is dead?!
		if(pimpas.HTTPRequest.isFinished(this.status)) {
			// is dead but transport still alive? WTF??
			// throw it away one more time and forever
			try {
				this.transport.abort( );
			} catch(e) {
				this.log.error(e.message);
				// dammit, we dont want u anymore, can't u understand????
			}
			return;
		}
		switch(this.transport.readyState) {
			case 1:
				this.status = this.callListeners(pimpas.HTTPRequest.events.onLoading);
			break;
			
			case 2:
				this.status = this.callListeners(pimpas.HTTPRequest.events.onLoaded);
			break;
			
			case 3:
				this.status = this.callListeners(pimpas.HTTPRequest.events.onInteractive);
				this.lastCall = new Date().getTime();
			break;
			
			case 4:
				pimpas.HTTPRequest.activeRequests--;
				this.timer.stop( );
				var success =false;
				if(pimpas.Browser.isIE)
					this.transport.onreadystatechange = pimpas.emptyFunction;
				if(this.transport.status == 0 || this.transport.status == 200) {
					var xml = this.transport.responseXML;
					success = true;
					var obbj = this.transport.responseText;
					if(xml != null) {
						if (!xml.nodeType || pimpas.Browser.isIE)
							xml = pimpas.HTTPRequest.fixXML( this.transport.responseText );
						
						var xmlObject = new pimpas.XML(xml);
						obbj = xmlObject;
					}
					
					this.status = this.callListeners(pimpas.HTTPRequest.events.onComplete, this.transport.responseText, obbj, xml, this.transport);
					this.log.log(pimpas.Log.INFO, 'Object ['+this.id+'] FINISHED REQUEST!');
				} else {
					this.log.log(pimpas.Log.ERROR, 'Unrecognized Error in Object '+this.id+', ERROR: '+this.transport.statusText);
					this.status = this.callListeners(pimpas.HTTPRequest.events.onError, this.transport.statusText);
				}
			break;
		}
	},
	abort: function() {
		if(!pimpas.HTTPRequest.isFinished(this.status)) {
			pimpas.HTTPRequest.activeRequests--;
			if(this.timer.isExecuting())
				this.timer.stop( );
			this.status = this.callListeners(pimpas.HTTPRequest.events.onAbort);
			try {
				this.transport.abort( );
			} catch(e) {
				this.log.error(e.message);
			}
			this.log.info('Request Object ['+this.id+'] aborted!');
		}
	},
	toString: function() {
		return "[PIMPAS HTTPREQUEST OBJECT]";
	}
}

);

pimpas.Extends(pimpas.HTTPRequest, {
   methods: {
		GET: "get",
		POST: "post"
	},
	activeRequests: 0,
	createTransport: function( ) {
		var obj = null;
		if(pimpas.Browser.isMozilla)
			obj = obj = new XMLHttpRequest();
		else {
			try {
				obj = new ActiveXObject('Microsoft.XMLHTTP');
			} catch(e) {
				try {
					obj = new ActiveXObject("MSXML2.DOMDocument");
				} catch(e1) {
					try {
						obj = new XMLHttpRequest();
					} catch(e2) {
						// well, is not my fault ur dummy stupid fucked browser!	
						// eat my exception
						throw e2;
					}
				}
			}
		}
		return obj;
	},
	fixXML: function( xml ) {
		var s = "" + xml;
		if (window.ActiveXObject) {
			xml = new ActiveXObject("MSXML2.DOMDocument");
			xml.loadXML(s);
		} else if(document.implementation)  {
			var parser = new DOMParser();
			xml = parser.parseFromString(s,"text/xml");    
		}
		
		return xml;
	},
	bypassMozilla: function() {
		if(pimpas.Browser.isMozilla)
			try {
				netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
			} catch (e) {
			}
	},
	events: {
		unInitialized: "Uninitialized",
		onCreate: "onCreate",
		onInitialize: "onInitialize",
		onLoading: "onLoading",
		onLoaded: "onLoaded",
		onInteractive: "onInteractive",
		onComplete: "onComplete",
		onError: "onError",
		onAbort: "onAbort",
		onResponse: "onResponse"
	},
	getInstance: function() {
		return HTTPRequestPool.get();
	},
	requests: new Array(),
	defaultTime: 60000,
	abortAll: function( ) {
		while(this.requests.length>0) {
			try {
				this.requests.pop().abort( );
			} catch(e) {
			}
		}
	},
	globalListeners: new Array(),
	addGlobalListener: function(t) {
		this.globalListeners.push(t);
	},
	isFinished: function(status) {
		return (status == pimpas.HTTPRequest.events.onComplete || status == pimpas.HTTPRequest.events.onError || status == pimpas.HTTPRequest.events.onAbort);
	}
}
);

pimpas.HTTPRequest.Pool = Class.create( );
pimpas.Extends(pimpas.HTTPRequest.Pool.prototype, 		   			   
	{
		poolSize: 10,
		freeSlots: 0,
		initialized: false,
		isInitialized: function( ) {
			return this.initialized;
		},
		pool: new Array(),
		waitTime: 5000,
		getWaitTime: function( ) {
			return this.waitTime;
		},
		setWaitTime: function(t) {
			this.waitTime = t;
		},
		maxAttempts: 10,
		getMaxAttempts: function( ) {
			return this.maxAttempts;	
		},
		setMaxAttempts: function(t) {
			this.maxAttempts = t;
		},
		setPoolSize: function(t) {
			this.poolSize = t;
		},
		getPoolSize: function() {
			return this.poolSize;
		},
		get: function() {
			if(!this.isInitialized()) return null;
			
			if(this.freeSlots > 0) {
				var obj = this.pool.shift();
				this.freeSlots--;
				this.log.log(pimpas.Log.INFO, "[HTTPREQUEST POOL]: Getting HTTPREQUEST from Pool. Lefts: "+this.freeSlots);
				return obj;
			} else {
				if(arguments.length == 1) {
					var n = parseInt(arguments[0]);
					if(isNaN(n)) return this.get(0);
					n+=1;
					if(n > this.maxAttempts) throw new NoHttpRequestInPoolException("try again later");
					return this.get(n);
				}
			}
			return this.get(0);
		},
		put: function(obj) {
			if(!this.isInitialized()) return null;
			
			if(!(obj instanceof pimpas.HTTPRequest)) return;
			if(this.freeSlots == this.getPoolSize()) return;
			obj.cleanUp( );
			obj.setPooled( true );
			this.pool.push(obj);
			this.freeSlots++;
			this.log.log(pimpas.Log.INFO, "[HTTPREQUEST POOL]: Adding HTTPREQUEST in Pool. Lefts: "+this.freeSlots);
		},
		initialize: function() {
			this.id = pimpas.globalID++;
			this.log = new pimpas.Log();
		},
		init: function() {
			if(this.initialized) return;
			this.initialized = true;
			if(arguments.length > 0)
				if(!isNaN(arguments[0]))
					this.setPoolSize(parseInt(arguments[0]));
			for(var i=0;i<this.getPoolSize();i++)
				this.put(new pimpas.HTTPRequest());
				
			this.log.log(pimpas.Log.INFO, 'Pool ['+this.id+'] initialized!');
		}
	}
);
// exceptions
NoHttpRequestInPoolException = Class.create();
pimpas.Extends(NoHttpRequestInPoolException.prototype, pimpas.Object);
pimpas.Extends(NoHttpRequestInPoolException.prototype,
			   {
				   toString: function( ) {
						return "NoHttpRequestInPoolException";
				   }
			   }
);
UrlNotFoundException = Class.create();
pimpas.Extends(UrlNotFoundException.prototype, pimpas.Object);
pimpas.Extends(UrlNotFoundException.prototype,
			   {
				   toString: function( ) {
						return "UrlNotFoundException";
				   }
			   }
);
RequestAlreadyRunning = Class.create();
pimpas.Extends(RequestAlreadyRunning.prototype, pimpas.Object);
pimpas.Extends(RequestAlreadyRunning.prototype,
			   {
				   toString: function( ) {
						return "RequestAlreadyRunning";
				   }
			   }
);

pimpas.Extends(pimpas.HTTPRequest.Pool.prototype, pimpas.Object);
var HTTPRequestPool = new pimpas.HTTPRequest.Pool();

pimpas.HTTPRequest.Queue = Class.create( );
pimpas.Extends(pimpas.HTTPRequest.Queue.prototype,
	{
		queue: null,
		timer: null,
		executing: null,
		listener: null,
		handleQueue: function() {
			if(this.executing != null) return;
			if(this.queue.length > 0) {
				this.executing = this.queue.shift();
				this.log.info("[Starting request from pool]");
				this.executing.request( );
			}
		},
		callBack: function(object, evt) {
			if(evt == pimpas.HTTPRequest.events.onComplete ||
			   evt == pimpas.HTTPRequest.events.onAbort ||
			   evt == pimpas.HTTPRequest.events.onError) {
			    this.log.info("[Request Finished!]");
				
			    new pimpas.Timer(100, function(){
					if(this.executing == null) {
						this.handleQueue( );
						return;
					}					
					if(this.executing.isPooled()) {
						this.log.info("[Returning Request to Pool!]");
						HTTPRequestPool.put( this.executing );
					} else
						this.executing.cleanUp( );
					this.executing = null;
					this.handleQueue( );
				}, this).go( );
			}
		},
		initialize: function() {
			this.queue = new Array();
			this.timer = new pimpas.Interval(300, this.handleQueue, this);
			this.id = pimpas.globalID++;
			this.log = new pimpas.Log();
			var temp = this;
			this.listener = new pimpas.HTTPRequest.Listener();
			pimpas.Extends(this.listener, {
								callBack: function(obj, evt) {
									temp.callBack(obj, evt);
								}
						   }
			);
			this.timer.go();
		},
		add: function(req) {
			if(!(req instanceof pimpas.HTTPRequest)) {
				this.log.log(pimpas.Log.ERROR, "Object ["+req+"] its not type of pimpas.HTTPRequest.");
				return;
			}
			
			req.addListener(this.listener);
			req.queueMode = true;
			this.queue.push(req);
			//this.handleQueue( );
		},
		remove: function(req) {
			
		},
		current: function() {
			return this.executing;
		}
	}
);
var HTTPRequestQueue = new pimpas.HTTPRequest.Queue();pimpas.ImportJS = Class.create( );
pimpas.Extends(pimpas.ImportJS, pimpas.Object);

pimpas.Extends(pimpas.ImportJS,
	{
		importScript: function(url, async) {
			if(url == null) throw new UrlNotFoundException();
			this.log.debug("[ImportJS]: Url => "+url);
			// create request
			var request = new pimpas.HTTPRequest( );
			// sync
			request.setAsync((async!=null&&async!=undefined) ? async : true);
			request.setUrl(url);
			request.setRequestMethod(pimpas.HTTPRequest.methods.GET);
			request.addParameter("date", new Date().getTime());
			request.addListener(pimpas.ImportJS.Listener);
			request.request( );
		}
	}
);

pimpas.ImportJS.Listener = Class.create( );
pimpas.Extends(pimpas.ImportJS.Listener, pimpas.HTTPRequest.Listener.prototype);
pimpas.Extends(pimpas.ImportJS.Listener,
	{
		callBack: function(obj, evt, text, xmlObject, xmlDocument) {
			switch(evt) {
				case pimpas.HTTPRequest.events.onComplete:
					// eval text
					try {
						eval(text);
					} catch(e) {
						throw new EvalScriptException(e);	
					}
				break;
				
				case pimpas.HTTPRequest.events.onError:
					// throw exception
					throw new ImportScriptException();
				break;
				case pimpas.HTTPRequest.events.onAbort:
					// throw exception
					throw new ImportScriptException();
				break;
			}
		}
	}
);

// exceptions
ImportScriptException = Class.create();
pimpas.Extends(ImportScriptException.prototype, pimpas.Object);
pimpas.Extends(ImportScriptException.prototype,
			   {
				   toString: function( ) {
						return "ImportScriptException";
				   }
			   }
);

EvalScriptException = Class.create();
pimpas.Extends(EvalScriptException.prototype, pimpas.Object);
pimpas.Extends(EvalScriptException.prototype,
			   {
				   ex: null,
				   initialize: function(e) {
						this.id=pimpas.globalID++;
						this.log = new pimpas.Log();
						this.ex = e;
				   },
				   toString: function( ) {
						return "EvalScriptException => "+((this.ex!=null) ? this.ex.message : "");
				   }
			   }
);
pimpas.ImportJS.initialize();pimpas.Format = Class.create( );
pimpas.Extends(pimpas.Format, pimpas.Object);

pimpas.Extends(pimpas.Format,
	{
		initialize: function() {
			this.id = pimpas.globalID++;
			this.log = new pimpas.Log();
			this.listener = new pimpas.Listener();
			pimpas.Extends(this.listener,
				{
					callBack: function(event, el, mask, listener, apply) {
						event = pimpas.DOM.Event.fixEvent(event);
						var id = ((el.id==null) ? el.name : el.id);
						this.log.debug("[Callback Format]: Apply? "+apply+", Field: "+el+", Mask: "+mask);
						if(pimpas.DOM.Event.getKeyPressed(event) == 8 || pimpas.DOM.Event.getKeyPressed(event) == 46) {
							// backspace or delete
							return;
						}
						if(listener != null) {
							this.log.debug('[Callback Format]: Calling listener BEFORE!');
							listener.callBack.bind(listener, pimpas.Format.time.BEFORE, el, mask)();
						}
						if(!apply) {
							this.log.debug("[Callback Format]: Cleaning field...");
							var stuffs = new Array();
							for(var i=0;i<mask.length;i++)
								if(mask.charAt(i) != '#')
									if(!stuffs.have(mask.charAt(i)))
										stuffs.push(mask.charAt(i));
							var tmp = null;
							var value = pimpas.DOM.getObjectValue( el );
							while(stuffs.length > 0) {
								tmp = stuffs.pop();
								while(value.indexOf(tmp)>=0)
									value = value.replace(tmp, "");
							}
							pimpas.DOM.setObjectValue( el, value );
						} else {
							this.log.debug("[Callback Format]: Executing format...");
							var value = pimpas.DOM.getObjectValue( el );
							var vValue = "";
							var p = new Array();
							for(var i=0;i<value.length;i++)
								if(!isNaN(Number(value.charAt(i))))
									p.push(value.charAt(i));		
							var vMask = mask;
							while(vMask.indexOf('#')>=0)
								vMask = vMask.replace('#', 'xX');
							var i = 0;
							vValue = vMask;
							while(i < p.length)
								vValue = vValue.replace('xX', p[i++]);
							var t = vValue.indexOf('xX');
							if(t >=0) vValue = vValue.substring(0, t);
														
							pimpas.DOM.setObjectValue( el, vValue );
						}
						if(listener != null) {
							this.log.debug('[Callback Format]: Calling listener AFTER!');
							listener.callBack.bind(listener, pimpas.Format.time.AFTER, el, mask)();
						}
					}
				}
			);
		},
		install: function(element, cleanEvt, applyEvt, mask, listener) {
			var el = pimpas.DOM.getElement(element);
			if(!pimpas.DOM.isDefined(el)) {
				this.log.error("Can't find HTML Element with id/name ["+element+"]");
				return;
			}
			
			var id = ((el.id==null) ? el.name : el.id);
			this.log.info("[Installing Format] => Field: "+id+", Mask: "+mask+", Listener: "+listener);
			var clean = function(event) { pimpas.Format.listener.callBack(event, element, mask, listener, false) };
			var apply = function(event) { pimpas.Format.listener.callBack(event, element, mask, listener, true) };
			if(cleanEvt != null)
				pimpas.DOM.Event.addListener( el, cleanEvt, clean, true );
			pimpas.DOM.Event.addListener( el, applyEvt, apply, true );
		},
		listener: null,
		time:
			{
				BEFORE: "before",
				AFTER: "after"
			}
	}
);

pimpas.Format.initialize( );pimpas.Utils = Class.create( );
pimpas.Extends(pimpas.Utils, pimpas.Object);

pimpas.Utils.DefaultListener = Class.create( );
pimpas.Extends(pimpas.Utils.DefaultListener.prototype, pimpas.Listener.prototype);
pimpas.Extends(pimpas.Utils.DefaultListener.prototype,
	{
		element: null,
		initialize: function(element) {
			this.id = pimpas.globalID++;
			this.log = new pimpas.Log();
			this.element = element;	
		}
	}
);

pimpas.Extends(pimpas.Utils,
	{
		disableFocus: function() {
			var el = null;
			for(var i=0;i<arguments.length;i++) {
				el = pimpas.DOM.getElement( arguments[i] );
				if(!pimpas.DOM.isDefined(el)) {
					this.log.error("Can't find element with id/name ["+arguments[i]+"]");
					continue;
				}
				this.log.debug("[Disabling focus for Element {"+arguments[i]+"}]");
				var listener = new pimpas.Utils.DefaultListener(el);
				pimpas.Extends(listener,
					{
						callBack: function(event) {
							event = pimpas.DOM.Event.fixEvent(event);
							// give focus to next child
							pimpas.DOM.Event.stop(event);
							this.element.blur();
							var parent = this.element.parentNode;
							if(parent == null)
								return;
							
							// give focus to next child
							var child = null;
							var found = false;
							for(var i=0;i<parent.childNodes.length;i++) {
								if(found) {
									if(pimpas.DOM.isField(parent.childNodes[i])) {
										child = parent.childNodes[i];
										break;
									}
								}
								if(parent.childNodes[i] == this.element) {
									found = true;
									continue;
								}
							}
							
							if(child == null) return;
							
							pimpas.DOM.focus( child );
						}
					}
				);
				var func = function(event) { listener.callBack(event); };
				pimpas.DOM.Event.addListener( el, pimpas.DOM.Event.FOCUS, func, true);
				
				return listener;
			}
		}
	}
);

pimpas.Utils.initialize( );pimpas.CleanUp = Class.create( );
pimpas.Extends(pimpas.CleanUp, pimpas.Object);
pimpas.Extends(pimpas.CleanUp,
   {
	   interval: null,
	   time: 6*100000,
   	   initialize: function() {
			this.id = pimpas.globalID++;
			this.log = new pimpas.Log();
			this.interval = new pimpas.Interval(this.time, pimpas.CleanUp.doClean, pimpas.CleanUp);
			this.interval.go();
	   },
	   doClean: function() {
		   //this.log.info("[CleanUp Procedure]: Cleaning all logs!");
		   for(var i=0;i<pimpas.Log.instances.length;i++)
				pimpas.Log.instances[i].flush( );
	   }
   }
);

pimpas.CleanUp.initialize( );pimpas.AJAX = pimpas.HTTPRequest;
/*
pimpas.Extends(pimpas.AJAX.prototype, pimpas.HTTPRequest.ListenerSupport.prototype);
pimpas.Extends(pimpas.AJAX.prototype, pimpas.HTTPRequest.ListenerSupport.prototype);
*/pimpas.AJAX.Validate = Class.create( );
pimpas.Extends(pimpas.AJAX.Validate.prototype, pimpas.Object);pimpas.AJAX.Populate = Class.create( );
pimpas.Extends(pimpas.AJAX.Populate.prototype, pimpas.Object);
pimpas.Extends(pimpas.AJAX.Populate.prototype, pimpas.ListenerSupport.prototype);

pimpas.AJAX.Populate.Listener = Class.create( );
pimpas.Extends(pimpas.AJAX.Populate.Listener.prototype, pimpas.Listener.prototype);
pimpas.Extends(pimpas.AJAX.Populate.prototype, pimpas.AJAX.Populate.Listener.prototype);
pimpas.AJAX.Populate.events = Class.create( );
pimpas.Extends(pimpas.AJAX.Populate.events,
   {
	   unInitialize: "unInitialize",
	   onRequesting: "onRequesting",
	   onRequestComplete: "onRequestComplete",
	   onPopulateStarted: "onPopulateStarted",
	   onPopulateEnded: "onPopulateEnded",
	   onPopulateError: "onPopulateError",
	   onPopulateAbort: "onPopulateAbort"
   }
);

pimpas.Extends(pimpas.AJAX.Populate.prototype, 
   {
		object: null,
		request: null,
		status: null,
		setObject: function(t) {
			this.object = pimpas.DOM.getElement(t);
		},
		getObject: function() {
			return this.object;
		},
		setRequest: function(t) {
			this.request = t;
		},
		getRequest: function() {
			return this.request;
		},
		initialize: function() {
			this.id = pimpas.globalID++;
			this.log = new pimpas.Log();
			this.status = pimpas.AJAX.Populate.events.unInitialize;
			this.listeners = new Array();
		},
		processResponse: function(text, xml) {
			try {
				this.status = this.callListeners(pimpas.AJAX.Populate.events.onPopulateStarted);
				var iterator = xml.eval( new pimpas.XML.Xpath( '//ajax//elements//element' ) );
				var handle = null;
				var handleObject = null;				
				while((el=iterator.iterateNext())!=null) {
					handle = xml.getAsText( xml.eval( new pimpas.XML.Xpath( 'handler' ), el ).iterateNext( ) );
					this.log.log(pimpas.Log.INFO, 'Creating Handler type ['+handle+'] for object '+this.id);
					handleObject = eval("new "+handle+"()");
					handleObject.populate( xml, el );
				}
				
				this.status = this.callListeners(pimpas.AJAX.Populate.events.onPopulateEnded, text, xml);
				this.log.info("[AJAX-POPULATE]: Finished Populate with no errors!");
			} catch(e) {
				this.log.error("[AJAX-POPULATE]: Error executing populate with handler ["+handle+"]");
				this.status = this.callListeners(pimpas.AJAX.Populate.events.onPopulateError, e.message);
				throw e;
			}
		},
		callBack: function(obj, evt, text, xml) {
			this.callListeners(evt, text, xml);
			switch(evt) {
				case pimpas.HTTPRequest.events.onInitialize:
					this.status = this.callListeners(pimpas.AJAX.Populate.events.onRequesting);
				break;
				
				case pimpas.HTTPRequest.events.onComplete:
					this.status = this.callListeners(pimpas.AJAX.Populate.events.onRequestComplete);
					new pimpas.Timer(50, function(){this.processResponse( text, xml )}, this).go();
				break;
				
				case pimpas.HTTPRequest.events.onError:
					this.status = this.callListeners(pimpas.AJAX.Populate.events.onPopulateError, text);
				break;
				
				case pimpas.HTTPRequest.events.onAbort:
					this.status = this.callListeners(pimpas.AJAX.Populate.events.onPopulateAbort);
				break;
			}
		},
		execute: function() {
			if(this.getRequest() == null) {
				this.log.log(pimpas.Log.ERROR, 'cannot execute populate without object request!');
				return;
			}
			this.getRequest().addListener( this );
			if(this.getRequest( ).queueMode)
				HTTPRequestQueue.add(this.getRequest( ));
			else
				this.getRequest().request( );
		}
   }
);

pimpas.AJAX.Populate.Object = Class.create( );
pimpas.Extends(pimpas.AJAX.Populate.Object.prototype, pimpas.Object);
pimpas.Extends(pimpas.AJAX.Populate.Object.prototype,
   {
	   object: null,
	   setObject: function(t) {
	   		this.object = t;  
	   },
	   getObject: function() {
	    	return this.object;  
	   },
	   initialize: function() {
	    	this.id = pimpas.globalID++;
			this.log = new pimpas.Log();
	   },
	   populate: function(xmlObject, xmlElement) {
       		
	   }
   }
);pimpas.AJAX.Populate.Input = Class.create( );
pimpas.Extends(pimpas.AJAX.Populate.Input.prototype, pimpas.AJAX.Populate.Object.prototype);
pimpas.Extends(pimpas.AJAX.Populate.Input.prototype,
   {
	   populate: function(xmlObject, xmlElement) {
		    this.log.log(pimpas.Log.INFO, 'Executing Input Populate... Object: '+this.id);
			var id = xmlObject.getAsText( xmlObject.eval( new pimpas.XML.Xpath( 'id' ), xmlElement).iterateNext( ) );
			if(!pimpas.DOM.isInput(id)) {
				this.log.log(pimpas.Log.ERROR, 	'The Object with ID ['+this.id+'] ITS NOT INPUT!!!!');
				return;
			}
			
			var value = xmlObject.getAsText( xmlObject.eval( new pimpas.XML.Xpath( 'value' ), xmlElement).iterateNext( ) );
			this.log.log(pimpas.Log.INFO, '[POPULATE]: Setting Object value => ID: '+id+', VALUE: '+value);
			pimpas.DOM.setObjectValue( id, value );
	   }
   }
);pimpas.AJAX.Populate.Select = Class.create( );
pimpas.Extends(pimpas.AJAX.Populate.Select.prototype, pimpas.AJAX.Populate.Object.prototype);
pimpas.Extends(pimpas.AJAX.Populate.Select.prototype,
   {
	   populate: function(xmlObject, xmlElement) {
		    this.log.log(pimpas.Log.INFO, 'Executing Select Populate... Object: '+this.id);
			
			var entries = xmlObject.eval( new pimpas.XML.Xpath( '//option' ) );
			var id = xmlObject.getAsText( xmlObject.eval( new pimpas.XML.Xpath( 'id' ), xmlElement).iterateNext( ) );
			if(!pimpas.DOM.isSelect(id)) {
				this.log.log(pimpas.Log.ERROR, 	'The Object with ID ['+this.id+'] ITS NOT SELECT!!!!');
				return;
			}
			
			var entry = null;
			var label = null;
			var value = null;
			var selected = null;
			pimpas.DOM.clearAllOptions( id );
			while((entry=entries.iterateNext())!=null) {
				label = xmlObject.getAsText( entry );
				value = xmlObject.getAttributeValue( entry, 'value' );
				selected = xmlObject.getAttributeValue( entry, 'selected' );
				pimpas.DOM.addOption( id, label, value );
				if(selected == 'true' || selected == 'selected')
					pimpas.DOM.setObjectValue( id, value );
			}
	   }
   }
);pimpas.AJAX.Populate.Radio = Class.create( );
pimpas.Extends(pimpas.AJAX.Populate.Radio.prototype, pimpas.AJAX.Populate.Object.prototype);
pimpas.Extends(pimpas.AJAX.Populate.Radio.prototype,
   {
	   populate: function(xmlObject, xmlElement) {
		    this.log.log(pimpas.Log.INFO, 'Executing Radio Populate... Object: '+this.id);
			id = xmlObject.getAsText( xmlObject.eval( new pimpas.XML.Xpath( 'id' ), xmlElement).iterateNext( ) );
			if(!pimpas.DOM.isRadio(id)) {
				this.log.log(pimpas.Log.ERROR, 	'The Object with ID ['+this.id+'] ITS NOT RADIO!!!!');
				return;
			}
			pimpas.DOM.setObjectValue( id, null );
			value = xmlObject.getAsText( xmlObject.eval( new pimpas.XML.Xpath( 'value' ), xmlElement).iterateNext( ) );
			this.log.log(pimpas.Log.INFO, '[POPULATE]: Setting Object value => ID: '+id+', VALUE: '+value);
			
			pimpas.DOM.setObjectValue( id, value );
	   }
   }
);pimpas.AJAX.Populate.Checkbox = Class.create( );
pimpas.Extends(pimpas.AJAX.Populate.Checkbox.prototype, pimpas.AJAX.Populate.Object.prototype);
pimpas.Extends(pimpas.AJAX.Populate.Checkbox.prototype,
   {
	   populate: function(xmlObject, xmlElement) {
		    this.log.log(pimpas.Log.INFO, 'Executing Checkbox Populate... Object: '+this.id);
			var entries = xmlObject.eval( new pimpas.XML.Xpath( '//values//value' ) );
			var id = xmlObject.getAsText( xmlObject.eval( new pimpas.XML.Xpath( 'id' ), xmlElement).iterateNext( ) );
			if(!pimpas.DOM.isCheckbox(id)) {
				this.log.log(pimpas.Log.ERROR, 	'The Object with ID ['+this.id+'] ITS NOT Checkbox!!!!');
				return;
			}
			
			pimpas.DOM.setObjectValue( id, null );
			var values = [];
			var i=0;
			var entry = null;
			while((entry=entries.iterateNext())!=null)
				values[i++] = xmlObject.getAsText( entry );
			
			pimpas.DOM.setObjectValue( id, values.join() );
	   }
   }
);pimpas.AJAX.Populate.Html = Class.create( );
pimpas.Extends(pimpas.AJAX.Populate.Html.prototype, pimpas.AJAX.Populate.Object.prototype);
pimpas.Extends(pimpas.AJAX.Populate.Html.prototype,
   {
	   populate: function(xmlObject, xmlElement) {
		    this.log.log(pimpas.Log.INFO, 'Executing Html Populate... Object: '+this.id);
			id = xmlObject.getAsText( xmlObject.eval( new pimpas.XML.Xpath( 'id' ), xmlElement).iterateNext( ) );
			value = xmlObject.getAsText( xmlObject.eval( new pimpas.XML.Xpath( 'value' ), xmlElement).iterateNext( ) );
			this.log.log(pimpas.Log.INFO, '[POPULATE]: Setting Object value => ID: '+id+', VALUE: '+value);
			pimpas.DOM.update( id, value );
	   }
   }
);pimpas.XML = Class.create( );
pimpas.Extends(pimpas.XML.prototype, pimpas.Object);
pimpas.Extends(pimpas.XML.prototype, 
   {
	   xmlObject: null,
	   resolver: null,
	   evalBrowser: null,
	   getAsTextBrowser: null,
	   getAttributeValueBrowser: null,
	   initialize: function(xml) {
			this.id = pimpas.globalID++;
			this.log = new pimpas.Log( );
	   		this.xmlObject = xml;
			if(!pimpas.Browser.isIE) {
				this.resolver = this.xmlObject.createNSResolver( this.xmlObject.ownerDocument == null ? this.xmlObject.documentElement : this.xmlObject.																																						ownerDocument.documentElement);
				this.evalBrowser = this.evalMozilla;
				this.getAsTextBrowser = this.getAsTextMozilla;
				this.getAttributeValueBrowser = this.getAttributeValueMozilla;
			} else {
				this.evalBrowser = this.evalIE;
				this.getAsTextBrowser = this.getAsTextIE;
				this.getAttributeValueBrowser = this.getAttributeValueIE;
			}
	   },
	   eval: function(xpath, el) {
			if(!(xpath instanceof pimpas.XML.Xpath)) {
				this.log.log(pimpas.Log.ERROR, "Xpath need be child of class pimpas.XML.Xpath");
				return;
			}
			
			return this.evalBrowser.bind(this, (el!=undefined && el!=null) ? el : this.xmlObject, xpath)();
	   },
	   evalMozilla: function(el, xpath) {
		    return new pimpas.XML.MozillaIterator(this.xmlObject.evaluate(xpath.value, el, this.resolver, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null ));
	   },
	   evalIE: function(el, xpath) {
	   		return new pimpas.XML.IEIterator(el.selectNodes(xpath.value));
	   },
	   getAsText: function(el) {
		   return this.getAsTextBrowser.bind(this, el)();
	   },
	   getAsTextMozilla: function(el) {
		   return el.textContent;
	   },
	   getAsTextIE: function(el) {
		   return el.text;
	   },
	   getAttributeValue: function(el, name) {
		   return this.getAttributeValueBrowser.bind(this, el, name)();
	   },
	   getAttributeValueMozilla: function(el, name) {
		   return el.getAttribute(name);
	   },
	   getAttributeValueIE: function(el, name) {
		   return el.getAttribute(name);
	   },
	   toString: function() {
			try {
				return (pimpas.Browser.isMozilla) ? (new XMLSerializer()).serializeToString(this.xmlObject) : object;
			} catch(e) {
				return object.toString( );	
			}
	   }
   }
);
pimpas.XML.Iterator = Class.create( );
pimpas.Extends(pimpas.XML.Iterator.prototype,
   {
	   initialize: function(r) {
		   this.result = r;
	   },
	   iterateNext: function() {
		   return null;
	   },
	   hasNext: function() {
	   	   return false;  
	   },
	   toString: function() {
	   		return "[XML ITERATOR]";   
	   }
   }
);
pimpas.XML.MozillaIterator = Class.create( );
pimpas.XML.IEIterator = Class.create( );
pimpas.Extends(pimpas.XML.MozillaIterator.prototype, pimpas.XML.Iterator.prototype);
pimpas.Extends(pimpas.XML.MozillaIterator.prototype,
   {
	   iterateNext: function() {
			return this.result.iterateNext( );   
	   },
	   hasNext: function() {
	   }
   }
);
pimpas.Extends(pimpas.XML.IEIterator.prototype, pimpas.XML.Iterator.prototype);
pimpas.Extends(pimpas.XML.IEIterator.prototype,
   {
	   pos: null,
	   count: null,
	   initialize: function(r) {
		   this.result = r;
		   this.pos = 0;
		   this.count = this.result.length;
	   },
	   hasNext: function() {
	   		return this.pos<this.count;
	   },
	   iterateNext: function() {
		   if(!this.hasNext()) return null;
		   var el = this.result[this.pos++];
		   return el;
	   }
   }
);pimpas.XML.Xpath = Class.create( );
pimpas.Extends(pimpas.XML.Xpath.prototype, pimpas.Object);
pimpas.Extends(pimpas.XML.Xpath.prototype, 
   {
	   value: null,
	   initialize: function(v) {
			this.id = pimpas.globalID++;
			this.log = new pimpas.Log();
			this.value = v;
	   }
   }
);pimpas.AJAX.Control = Class.create( );
pimpas.Extends(pimpas.AJAX.Control.prototype, pimpas.Object);
pimpas.Extends(pimpas.AJAX.Control.prototype, pimpas.Listener.prototype);
pimpas.Extends(pimpas.AJAX.Control.prototype,
	{
	element: null,
	initialize: function(el) {
		this.element = pimpas.DOM.getElement( el );
	},
	toString: function() {                                             
		return "[AJAX CONTROL LISTENER]";
	},
	callBack: function(obj, evt, text, xml) {
		switch(evt) {
			case pimpas.HTTPRequest.events.onInitialize:
				pimpas.DOM.toVisible( this.element );
			break;
			
			case pimpas.HTTPRequest.events.onComplete:				
				pimpas.DOM.toHidden( this.element );
			break;
			
			case pimpas.HTTPRequest.events.onError:
				pimpas.DOM.toHidden( this.element );
			break;
			
			case pimpas.HTTPRequest.events.onAbort:
				pimpas.DOM.toHidden( this.element );
			break;
		}
	}
  }
);pimpas.AJAX.MyFacesHax = new pimpas.AJAX.Populate.Listener();
pimpas.Extends(pimpas.AJAX.MyFacesHax,
			   {
					callBack: function(obj, evt, text, xml) {
						switch(evt) {
							case pimpas.AJAX.Populate.events.onPopulateEnded:
								// get jsf_sequence element
								// @deprecated
								/*								
								this.log.info("[MyFaces HAX]: Update jsf_sequence in all forms!");
								var jsf_sequence = xml.eval( new pimpas.XML.Xpath( '//ajax//jsf_sequence' ) ).iterateNext( );
								var newValue = null;
								var root = null;
								if(pimpas.DOM.isDefined( jsf_sequence )) {
									newValue = xml.getAsText( jsf_sequence );
									root = window.document.getElementsByTagName("form");
									for(var i=0;i<root.length;i++)
										this.updateGlobalField( root[i], newValue, "jsf_sequence" );
								}
								*/
								
								// get viewstate element
								this.log.info("[MyFaces HAX]: Update viewState in all forms!");
								var it = xml.eval( new pimpas.XML.Xpath( '//ajax//viewstate' ) );
								var vs = null;
								while((vs=it.iterateNext())!=null) {
									if(pimpas.DOM.isDefined( vs )) {
										newValue = xml.getAsText( vs );
										root = window.document.getElementsByTagName("form");
										var id = xml.getAttributeValue( vs, 'id' );
										for(var i=0;i<root.length;i++)
											this.updateGlobalField( root[i], newValue, id );
									}
								}
							break;
						}
					},
					updateGlobalField: function(el, value, fieldName) {
						if(pimpas.DOM.isDefined(el.name) || pimpas.DOM.isDefined(el.id))
							if(el.name == fieldName || el.id == fieldName) {
								this.log.info("[MyFaces HAX]: Element "+fieldName+" found, update!");
								pimpas.DOM.setObjectValue( el, value );
							}
								
							for(var i=0;i<el.childNodes.length;i++)
								this.updateGlobalField(el.childNodes[i], value, fieldName);
					}
			   }
);

pimpas.AJAX.HandlePopulateError = new pimpas.AJAX.Populate.Listener();
pimpas.Extends(pimpas.AJAX.HandlePopulateError,
			   {
					callBack: function(obj, evt, text, xml) {
						switch(evt) {
							case pimpas.AJAX.Populate.events.onPopulateError:
							break;
						}
					}
			   }
);

pimpas.AJAX.Populate.ProcessAJAX = Class.create( );
pimpas.Extends(pimpas.AJAX.Populate.ProcessAJAX, pimpas.Object);
pimpas.Extends(pimpas.AJAX.Populate.ProcessAJAX,
			   {
				    AJAXMODE: "AJAX_MODE_ENABLED",
					AJAXCALLER: "AJAX_CALLER",
					execute: function(obj, async, immediate, withForm, loading, extraParameters) {
						// create input populate
						obj = pimpas.DOM.getElement( obj );
						var ajaxPopulate = new pimpas.AJAX.Populate( );
						if(pimpas.DOM.isDefined(loading) && pimpas.DOM.getElement(loading) != null)
							ajaxPopulate.addListener( new pimpas.AJAX.Control( loading ) );
						// create request
						var ajaxRequest;
						if(!immediate) {
							HTTPRequestPool.init( );
							ajaxRequest = pimpas.HTTPRequest.getInstance( );
						} else
							ajaxRequest = new pimpas.HTTPRequest( );
						
						var trickRequest = ajaxRequest.request;
						ajaxRequest.request = function() {
							this.setAsync( async );
							// exclude any kind of buttons
							var excludeFilter = new pimpas.Filter( );
							excludeFilter.accept = function(element) {
								return (element == obj) || (element.type != 'button' && element.type != 'submit');
							}
							
							if(withForm == true)
								this.sendForm( obj, excludeFilter );
								
							// put ajax request identifier
							this.addParameter(pimpas.AJAX.Populate.ProcessAJAX.AJAXMODE, "true");
							this.addParameter(pimpas.AJAX.Populate.ProcessAJAX.AJAXCALLER, (obj.id) ? obj.id : obj.name);
							
							// process extra parameters
							if(pimpas.DOM.isDefined(extraParameters))
								for(var i=0;i<extraParameters.length;i++)
									this.addParameter(extraParameters[i].name, encodeURI(extraParameters[i].value));
							
							trickRequest.call(this);
						}
						
						// put the request
						ajaxPopulate.setRequest( ajaxRequest );
						// myfaces hax
						ajaxPopulate.addListener( pimpas.AJAX.MyFacesHax );
						ajaxPopulate.addListener( pimpas.AJAX.HandlePopulateError );
						// execute
						try {
						   ajaxPopulate.execute( );
						} catch(e) {
							
						}
				   }
			   }
);